package recallin.activities;

import java.io.File;
import java.util.ArrayList;

import org.mapsforge.android.maps.MapController;
import org.mapsforge.android.maps.MapView;
import org.mapsforge.android.maps.overlay.ArrayCircleOverlay;
import org.mapsforge.android.maps.overlay.ArrayItemizedOverlay;
import org.mapsforge.android.maps.overlay.ArrayWayOverlay;
import org.mapsforge.android.maps.overlay.ItemizedOverlay;
import org.mapsforge.android.maps.overlay.OverlayCircle;
import org.mapsforge.android.maps.overlay.OverlayItem;
import org.mapsforge.android.maps.overlay.OverlayWay;
import org.mapsforge.core.GeoPoint;

import recallin.activities.R.layout;
import recallin.gui.MapButton;
import recallin.gui.PaintPallett;
import recallin.gui.SelectionOverlays;
import recallin.location.LocationUtility;
import recallin.navigation.PathWay;
import recallin.navigation.Reader;
import recallin.navigation.ReaderFootMode;
import recallin.navigation.Trigger;
import recallin.navigation.talkback.Talkback;
import recallin.social.facebook.FacebookDialog;
import recallin.social.facebook.FacebookLoginButton;
import recallin.social.facebook.Places;
import recallin.social.facebook.SessionStore;
import recallin.social.facebook.Utility;
import recallin.social.twitter.TwitterDialog;
import recallin.social.twitter.TwitterLoginButton;
import recallin.social.twitter.TwitterUtils;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.Facebook;
import com.facebook.android.R;

/**
 * This class handles all communication between all classes. Also takes care of
 * the maprendering and socialnetwork connections.
 * 
 * @author philipmasek
 * 
 */

public class MainActivity extends org.mapsforge.android.maps.MapActivity {

	public static int screen_width;
	public static int screen_height;

	public static final String APP_ID = "311753652214466";
	public static final String[] PERMISSIONS = { "offline_access",
			"publish_stream", "user_photos", "publish_checkins", "photo_upload" };

	public final static int AUTHORIZE_ACTIVITY_RESULT_CODE = 0;
	public static final int FACEBOOK_DIALOG = 1111;
	public static final int TWITTER_DIALOG = 1112;
	public static final int FACEBOOK_LOGIN = 0;
	public static final int TWITTER_LOGIN = 419283;
	public static final int MAP_DIALOG = 012312;
	protected static final int UPDATE_ROUTE = 0;

	private MapButton location;
	private MapButton btnFacebook;
	private MapButton up;
	private MapButton btnTwitter;
	private MapButton navi;
	public static Handler mHandler;
	private MapController mapController;
	private MapView mapView;
	private GeoPoint[][] route;
	ProgressDialog dialog;
	private static Location currentLocation;
	private OverlayCircle circle;
	private ArrayCircleOverlay arrayCircleOverlay;
	private boolean centerOn = false;
	private static ArrayItemizedOverlay arrayItemizedOverlay;
	private static OverlayItem item;
	private LocationUtility locationUtility;
	private static GeoPoint destinationPoint;
	private static GeoPoint startPoint;
	private ArrayList<Trigger> triggers;
	private Talkback talkback;
	private BroadcastReceiver mKillReceiver;
	public static boolean startingRoute;

	public static final int CAR_MODE = 2908734;
	public static final int PEDESTRIAN_MODE = 1212;
	private static int mode = PEDESTRIAN_MODE;

	private OverlayWay way;
	private ArrayWayOverlay arrayWayOverlay;

	private static ArrayList<GeoPoint> startRoute;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		System.gc();

		screen_width = getWindowManager().getDefaultDisplay().getWidth();
		screen_height = getWindowManager().getDefaultDisplay().getHeight();

		Utility.mFacebook = new Facebook(APP_ID);
		Utility.mAsyncRunner = new AsyncFacebookRunner(Utility.mFacebook);
		SessionStore.restore(Utility.mFacebook, this);

		talkback = new Talkback(this);
		talkback.start();

		setContentView(R.layout.map_frame);
		location = new MapButton(this, R.drawable.btn_location);
		btnFacebook = new MapButton(this, R.drawable.btn_facebook);
		up = new MapButton(this, R.drawable.btn_menu);
		btnTwitter = new MapButton(this, R.drawable.btn_twitter);
		navi = new MapButton(this, R.drawable.btn_navi);

		mapView = new MapView(this);
		mapView.setClickable(true);
		mapView.setBuiltInZoomControls(true);
		mapView.setMapFile(new File(Environment.getExternalStorageDirectory()
				.getPath() + "/Recallin/maps/sweden.map"));

		FrameLayout frameLayout = (FrameLayout) findViewById(R.id.map_frame);
		LinearLayout linearLayout = new LinearLayout(this);
		linearLayout.setOrientation(LinearLayout.HORIZONTAL);
		linearLayout.setGravity(Gravity.BOTTOM);
		linearLayout.addView(location);
		linearLayout.addView(btnFacebook);
		linearLayout.addView(up);
		linearLayout.addView(btnTwitter);
		linearLayout.addView(navi);

		LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		if (locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) != null) {
			setCurrentLocation(locationManager
					.getLastKnownLocation(LocationManager.GPS_PROVIDER));
		} else if (locationManager
				.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) != null) {
			setCurrentLocation(locationManager
					.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
		}

		frameLayout.addView(mapView);
		frameLayout.addView(linearLayout);

		mapController = mapView.getController();

		arrayCircleOverlay = new ArrayCircleOverlay(
				PaintPallett.getCircleFillPaint(),
				PaintPallett.getCircleStrokePaint());
		circle = new OverlayCircle();
		arrayCircleOverlay.addCircle(circle);
		item = new OverlayItem();
		item.setMarker(ItemizedOverlay.boundCenter(getResources().getDrawable(
				R.drawable.location)));
		arrayItemizedOverlay = (new ArrayItemizedOverlay(getResources()
				.getDrawable(R.drawable.location)));
		arrayItemizedOverlay.addItem(item);

		arrayWayOverlay = new ArrayWayOverlay(PaintPallett.getWayFillPaint(),
				PaintPallett.getWayStrokePaint());
		way = new OverlayWay();
		arrayWayOverlay.addWay(way);
		mapView.getOverlays().add(arrayWayOverlay);
		mapView.getOverlays().add(arrayCircleOverlay);
		mapView.getOverlays().add(arrayItemizedOverlay);

		mHandler = new Handler() {

			private GeoPoint center;

			@Override
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case TWITTER_DIALOG:
					showDialog(TWITTER_DIALOG);
					break;
				case TWITTER_LOGIN:
					showDialog(TWITTER_LOGIN);
					break;
				case MAP_DIALOG:
					setDestinationPoint((GeoPoint) msg.obj);
					showDialog(MAP_DIALOG);
					break;

				case UPDATE_ROUTE:
					dialog.dismiss();
					break;
				case LocationUtility.LOCATION_CHANGED:
					if (getCurrentLocation() != null) {
						center = new GeoPoint(getCurrentLocation()
								.getLatitude(), getCurrentLocation()
								.getLongitude());
					}
					if (getTriggers() != null)
						if (getTriggers().size() > 0) {
							getTriggers().get(0);
//							System.out.println(getTriggers().get(0)
//									.getMessage()
//									+ " : "
//									+ getTriggers().get(0).getDistance());
//							System.out.println(calculateDistance(getTriggers()
//									.get(0).getGeoPoint(), center));
							double distance = calculateDistance(getTriggers()
									.get(0).getGeoPoint(), center);
							if (distance < getTriggers().get(0).getDistance()) {
								mHandler.post(new Runnable() {
									public void run() {
										String[] s = getTriggers().get(0)
												.getMessage().split(" ");
										ArrayList<String> list = new ArrayList<String>();
										for (int i = 0; i < s.length; i++) {
											list.add(s[i]);
										}
										talkback.queueSound(1, 10, s);
										getTriggers().remove(0);
									}
								});
							}
						}

					circle.setCircleData(center, getCurrentLocation()
							.getAccuracy());
					arrayCircleOverlay.requestRedraw();
					item.setPoint(center);
					arrayItemizedOverlay.requestRedraw();

					if (centerOn)
						mapView.getController().setCenter(center);

					break;

				case 666:
					mHandler.post(new Runnable() {
						public void run() {
							String t = "take the second exit on the left";
							String[] s = t.split(" ");
							ArrayList<String> list = new ArrayList<String>();
							for (int i = 0; i < s.length; i++) {
								list.add(s[i]);
							}
							if (centerOn) {
								mHandler.sendEmptyMessage(555);
							}

							talkback.queueSound(1, 0, s);
							getTriggers().remove(0);
						}
					});
					break;

				case 555:
					mapView.getController().setCenter((GeoPoint) msg.obj);
					break;
				default:
					break;
				}
				super.handleMessage(msg);
			}
		};

		location.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// mHandler.sendEmptyMessage(666);
				if (centerOn)
					centerOn = false;
				else
					centerOn = true;
			}
		});
		btnFacebook.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (Utility.mFacebook.isSessionValid())
					showDialog(FACEBOOK_DIALOG);
				else
					showDialog(FACEBOOK_LOGIN);
			}
		});
		up.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent intent = new Intent(MainActivity.this,
						MenuActivity.class);
				startActivity(intent);
				overridePendingTransition(
						recallin.activities.R.anim.slide_in_bottom,
						recallin.activities.R.anim.slide_out_top);
			}
		});
		btnTwitter.setOnClickListener(new OnClickListener() {
			private ProgressDialog dialog;

			@Override
			public void onClick(View v) {
				Thread thread = new Thread() {
					@Override
					public void run() {
//						System.out.println("Authenticating");
						TwitterUtils.isAuthenticated(MainActivity.this);
						if (MainActivity.this.dialog != null)
							dialog.dismiss();

						super.run();
					}
				};
				thread.start();
			}
		});
		navi.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent intent = new Intent(MainActivity.this,
						MenuActivity.class);
				intent.putExtra("tab_index", 4);
				startActivity(intent);
				overridePendingTransition(
						recallin.activities.R.anim.slide_in_bottom,
						recallin.activities.R.anim.slide_out_top);
			}
		});

		SelectionOverlays selectionOverlays = new SelectionOverlays(
				getResources().getDrawable(R.drawable.pin), this);

		mapView.getOverlays().add(selectionOverlays);

		locationUtility = new LocationUtility(locationManager,
				LocationManager.GPS_PROVIDER, mHandler, this);
		locationUtility.startLocationService();
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case FACEBOOK_DIALOG:
			return new FacebookDialog(this);
		case FACEBOOK_LOGIN:
			FacebookLoginButton loginButton = new FacebookLoginButton(this);
			loginButton.init(this, AUTHORIZE_ACTIVITY_RESULT_CODE,
					Utility.mFacebook, PERMISSIONS);
			return loginButton;
		case TWITTER_DIALOG:
			return new TwitterDialog(this);
		case TWITTER_LOGIN:
			return new TwitterLoginButton(this);
		case MAP_DIALOG:
			final Dialog dialog = new Dialog(this);
			dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
			dialog.setContentView(layout.map_dialog);
			ListView listView = (ListView) dialog.findViewById(R.id.mapdialog);
			String[] s = { "Take me here", "Save to favorites" };
			ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
					android.R.layout.simple_list_item_1, s);
			listView.setAdapter(adapter);
			listView.setOnItemClickListener(new OnItemClickListener() {
				@Override
				public void onItemClick(AdapterView<?> arg0, View v, int pos1,
						long pos2) {
					switch (pos1) {
					case 0:
						dialog.dismiss();
						startingRoute = true;
						startRoute();
						break;
					default:
						break;
					}

				}
			});
			return dialog;
		default:
			return super.onCreateDialog(id);
		}

	}

	@Override
	protected void onResume() {
		overridePendingTransition(recallin.activities.R.anim.slide_in_top,
				recallin.activities.R.anim.slide_out_bottom);
		if (Utility.mFacebook != null) {
			if (Utility.mFacebook.isSessionValid()) {
				Utility.mFacebook.extendAccessTokenIfNeeded(this, null);
			}
		}

		if (getDestinationPoint() != null && startingRoute) {
			if (getStartPoint() == null)
				setStartPoint(new GeoPoint(getCurrentLocation().getLatitude(),
						getCurrentLocation().getLongitude()));
			startRoute();
		}

		super.onResume();
	}

	public void startRoute() {
		startingRoute = false;
		if (getStartPoint() == null)
			setStartPoint(new GeoPoint(getCurrentLocation().getLatitude(),
					getCurrentLocation().getLongitude()));
//		System.out.println(getDestinationPoint().getLatitude() + " : "
//				+ getStartPoint().getLatitude());
		dialog = ProgressDialog.show(MainActivity.this, "", "Loading route!");
		// locationUtility.stopLocationService();
		Thread thread = new Thread() {

			@Override
			public void run() {
				Looper.prepare();

				PathWay pathWay;
				if (getMode() == CAR_MODE) {
					Reader reader = new Reader();
					pathWay = reader.executeQueryTest(getStartPoint(),
							getDestinationPoint());
				} else {
					ReaderFootMode reader = new ReaderFootMode();
					pathWay = reader.executeQueryTest(getStartPoint(),
							getDestinationPoint());

				}

//				System.out.println(pathWay);

				GeoPoint[][] route = pathWay.getGeopoint();
				way.setWayNodes(route);
				arrayWayOverlay.requestRedraw();

				setTriggers(pathWay.getTrigger());

				mHandler.sendEmptyMessage(UPDATE_ROUTE);
			}
		};
		thread.start();
	}

	public static ArrayList<GeoPoint> getStartRoute() {
		return startRoute;
	}

	public static void setStartRoute(ArrayList<GeoPoint> startRoute) {
		MainActivity.startRoute = startRoute;
	}

	public static GeoPoint getStartPoint() {
		return startPoint;
	}

	public static void setStartPoint(GeoPoint startPoint) {
		MainActivity.startPoint = startPoint;
	}

	public static GeoPoint getDestinationPoint() {
		return destinationPoint;
	}

	public static void setDestinationPoint(GeoPoint destinationPoint) {
		MainActivity.destinationPoint = destinationPoint;
	}

	public ArrayList<Trigger> getTriggers() {
		return triggers;
	}

	public void setTriggers(ArrayList<Trigger> triggers) {
		this.triggers = triggers;
	}

	@Override
	protected void onDestroy() {
		unregisterReceiver(mKillReceiver);
		super.onDestroy();
	}

	public static long calculateDistance(GeoPoint a, GeoPoint b) {
		double R = 6371; // km
		double dLat = Math.toRadians((b.getLatitude() - a.getLatitude()));
		double dLon = Math.toRadians(b.getLongitude() - a.getLongitude());
		double lat1 = Math.toRadians(a.getLatitude());
		double lat2 = Math.toRadians(b.getLatitude());
		double a1 = Math.sin(dLat / 2) * Math.sin(dLat / 2)
				+ Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1)
				* Math.cos(lat2);
		double c = 2 * Math.atan2(Math.sqrt(a1), Math.sqrt(1 - a1));
		double d = R * c;
		return (long) (d * 1000);

	}

	public static long calculateDistance(GeoPoint a, Location b) {
		double R = 6371; // km
		double dLat = Math.toRadians((b.getLatitude() - a.getLatitude()));
		double dLon = Math.toRadians(b.getLongitude() - a.getLongitude());
		double lat1 = Math.toRadians(a.getLatitude());
		double lat2 = Math.toRadians(b.getLatitude());
		double a1 = Math.sin(dLat / 2) * Math.sin(dLat / 2)
				+ Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1)
				* Math.cos(lat2);
		double c = 2 * Math.atan2(Math.sqrt(a1), Math.sqrt(1 - a1));
		double d = R * c;
		return (long) (d * 1000);

	}

	public static Location getCurrentLocation() {
		return currentLocation;
	}

	public static void setCurrentLocation(Location currentLocation) {
		System.out.println(currentLocation.getLatitude());
		MainActivity.currentLocation = currentLocation;
	}

	public static void addOverlayItem(OverlayItem overlayItem) {
		Message message = new Message();
		overlayItem.getPoint();
		message.obj = overlayItem.getPoint();
		message.what = 555;
		mHandler.sendMessage(message);
		arrayItemizedOverlay.clear();
		arrayItemizedOverlay.addItem(overlayItem);
		arrayItemizedOverlay.addItem(item);
		arrayItemizedOverlay.requestRedraw();
	}

	public static void setMode(int mode) {
		// if (mode == CAR_MODE) {
		// car.setTextColor(Color.parseColor("#1f69a2"));
		// pedestrian.setTextColor(Color.parseColor("#a8a8a8"));
		// } else {
		// pedestrian.setTextColor(Color.parseColor("#1f69a2"));
		// car.setTextColor(Color.parseColor("#a8a8a8"));
		// }
		mode = mode;
	}

	public static int getMode() {
		return mode;
	}

}
